﻿using System;
using System.Xml.Serialization;

namespace Altairis.OtpAuth.Core {
    [XmlRoot(ElementName = "timeOtpVerifier", Namespace = XmlNs.SERIALIZATION_NS_URL)]
    public class TimeOtpVerifier : OtpVerifier {

        // Constructors

        public TimeOtpVerifier() {
            this.Generator = new TimeOtpGenerator();
        }

        // Properties

        [XmlElement("generator")]
        public TimeOtpGenerator Generator { get; set; }

        // Methods

        public override bool VerifyOneTimePassword(string otp) {
            // Validate arguments
            if (otp == null) throw new ArgumentNullException("otp");
            if (string.IsNullOrWhiteSpace(otp)) throw new ArgumentException("Value cannot be empty or whitespace only string.", "otp");

            // Validate syntax
            var reqLength = this.Generator.Digits + (this.Generator.UseChecksumDigit ? 1 : 0);
            if (otp.Length < reqLength) otp = otp.PadRight(reqLength);
            if (!this.VerifyPasswordSyntax(otp, this.Generator)) return false;

            // Validate OTP
            var localTime = DateTime.UtcNow.AddSeconds(-this.ThrottlingCount * this.Generator.TimeStep);
            for (int i = 0; i < 1 + 2 * this.ThrottlingCount; i++) {
                if (otp.Equals(this.Generator.GenerateOneTimePassword(this.Secret, localTime))) return true;
                localTime = localTime.AddSeconds(this.Generator.TimeStep);
            }
            return false;
        }

    }
}
